﻿using Castle.DynamicProxy;
using MyCommon.Helper;
using Newtonsoft.Json;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace MyExtension.AOP
{
    public abstract class CacheAopBase : IInterceptor
    {
        /// <summary>
        /// AOP拦截方法
        /// </summary>
        /// <param name="invocation"></param>
        public abstract void Intercept(IInvocation invocation);

        protected string GetCustomCacheKey(IInvocation invocation)
        {
            var typeName = invocation.TargetType.Name;
            var methodName = invocation.Method.Name;
            var methodArgs = invocation.Arguments.Select(i => i).Take(3).ToList();
            string cacheKey = $"{typeName}:{methodName}";

            foreach (var item in methodArgs)
            {
                cacheKey = $"{cacheKey}{item}:";
            }
            cacheKey = cacheKey.TrimEnd(':');
            return cacheKey ;
        }

        protected static string GetArgumentValue(object arg)
        {
            if (arg is DateTime) return ((DateTime)arg).ToString("yyyyMMddHHmmss");
            if (!arg.IsNotEmptyOrNull()) return arg.ObjToString();
            if (arg != null)
            {
                if (arg is Expression)
                {
                    var obj = arg as Expression;
                    var result = Reslove(obj);
                    return MD5Helper.MD5Encrypt16(result);
                }
                else if (arg.GetType().IsClass)
                {
                    return MD5Helper.MD5Encrypt16(JsonConvert.SerializeObject(arg));
                }
                return $"value:{arg.ObjToString()}";
            }
            return string.Empty;
        }

        private static string Reslove(Expression expression)
        {
            ExpressionContext expContext = new ExpressionContext();
            expContext.Resolve(expression, ResolveExpressType.WhereSingle);
            var value = expContext.Result.GetString();
            var pars = expContext.Parameters;
            pars.ForEach(p => { 
                value = value.Replace(p.ParameterName,p.Value.ObjToString());
            });
            return value;
        }
    }
}
